/* colorbar.cpp */

#include <dodo_plot/widget/colorbar.h>
#include <dodo_plot/kernel/plotter.h>
#include <dodo_plot/widget/image.h>
#include <dodo_plot/kernel/operation.h>
#include <dodo_plot/kernel/picture.h>
#include <dodo_plot/kernel/pic.h>
#include <dodo_plot/kernel/p_node.h>

namespace dodo_plot
{

Colorbar::Colorbar(double width, double height, const Colormap& colormap, const Axis& axis, int mode, bool draw_arrow)
	: w_(width), h_(height),
	colormap_(colormap), axis_(axis),
	mode_(mode),
	draw_arrow_(draw_arrow)
{
	apply_default();
}
	
void Colorbar::set_border_color(const Color& color)
{
	border_color_ = color;
}

void Colorbar::set_border_width(double width)
{
	border_width_ = width;
}

void Colorbar::set_tick_length_ratio(double ratio)
{
	tick_length_ratio_ = ratio;
	if(tick_length_ratio_ > 1.0)
		tick_length_ratio_ = 1.0;
}

void Colorbar::set_label_distance(double distance)
{
	axis_.set_label_distance(distance);
}

void Colorbar::set_label_align_mode(int mode)
{
	axis_.set_label_align_mode(mode);
}

void Colorbar::apply_default()
{
	if(mode_ == HORIZONTAL)
		axis_.apply_mode(BOTTOM);
	else
		axis_.apply_mode(RIGHT);
	
	border_color_ = axis_.get_line_color();
	border_width_ = axis_.get_line_width();
	tick_length_ratio_ = 0.5;

	axis_.set_line_color(color_name::TRANSPARENT);

}

void Colorbar::draw(const Plotter& plotter) const
{
	plotter.save();
	plotter.begin_new_path();

	std::vector<int> v(colormap_.size());

	std::vector<double> tick_pos(axis_.tick_begin(), axis_.tick_end());
	double tick_pos_min = axis_.local_min();
	double tick_pos_max = axis_.local_max();

	for(int i = 0; i < v.size(); ++i)
	{
		v[i] = i;
	}
	Image bar(v.size(), 1, &v[0], colormap_, true);


	if(mode_ == HORIZONTAL)
	{
		double arrow_length = 2.0 * height() / width();
		if(arrow_length > 0.25)
			arrow_length = 0.25;

		Position main_bar_pos;
		if(draw_arrow_)
		{
			main_bar_pos = Position(arrow_length, 1.0 - arrow_length, 0, 1);
		}
		else
		{
			main_bar_pos = Position(0, 1, 0, 1);
		}

		Picture bar_pic = frame(bar, main_bar_pos.width(), main_bar_pos.height());

		Plotter bar_plotter = plotter.sub_plotter(
			main_bar_pos, 
			bar_pic.local_pos()
			);
		
		bar_pic.draw(bar_plotter);


		if(draw_arrow_)
		{
			//left_arrow
			plotter.begin_new_path();
			plotter.move_to(main_bar_pos.left, main_bar_pos.top);
			plotter.line_to(main_bar_pos.left, main_bar_pos.bottom);
			plotter.line_to(0.0, 0.5);
			plotter.close_path();
			plotter.set_color(colormap_.beyond_min());
			plotter.fill();
			//right_arrow
			plotter.move_to(main_bar_pos.right, main_bar_pos.top);
			plotter.line_to(1.0, 0.5);
			plotter.line_to(main_bar_pos.right, main_bar_pos.bottom);
			plotter.close_path();
			plotter.set_color(colormap_.beyond_max());
			plotter.fill();
		}
	
		Plotter axis_plotter = plotter.sub_plotter(
			Position(
				main_bar_pos.left, main_bar_pos.right,
				main_bar_pos.bottom, main_bar_pos.bottom
				),
			axis_.local_pos()
			);
		
		axis_.draw(axis_plotter);
		
		plotter.set_color(border_color_);
		plotter.set_line_width(border_width_);
		//Draw border
		plotter.move_to(main_bar_pos.left, main_bar_pos.top);
		plotter.line_to(main_bar_pos.right, main_bar_pos.top);
		if(draw_arrow_)
		{
			plotter.line_to(1.0, 0.5);
		}
		plotter.line_to(main_bar_pos.right, main_bar_pos.bottom);
		plotter.line_to(main_bar_pos.left, main_bar_pos.bottom);
		if(draw_arrow_)
		{
			plotter.line_to(0.0, 0.5);
		}
		plotter.close_path();
		plotter.stroke();

		//Draw ticks
		double tick_length = 1.0 * tick_length_ratio_ / 2;
		for(int i = 0; i < tick_pos.size(); ++i)
		{
			double tick_x_pos = (tick_pos[i] - tick_pos_min) / (tick_pos_max - tick_pos_min) * main_bar_pos.width() + main_bar_pos.left;
			plotter.move_to(tick_x_pos, 0.0);
			plotter.line_to(tick_x_pos, 0.0 + tick_length);
			plotter.move_to(tick_x_pos, 1.0);
			plotter.line_to(tick_x_pos, 1.0 - tick_length);
		}
		plotter.stroke();
	}
	else
	{
		double arrow_length = 2.0 * width() / height();
		if(arrow_length > 0.25)
			arrow_length = 0.25;
		Position main_bar_pos;
		if(draw_arrow_)
		{
			main_bar_pos = Position(0, 1, arrow_length, 1.0 - arrow_length);
		}
		else
		{
			main_bar_pos = Position(0, 1, 0, 1);
		}
		
		bar.rotate_270();
		Picture bar_pic = frame(bar, main_bar_pos.width(), main_bar_pos.height());

		Plotter bar_plotter = plotter.sub_plotter(
			main_bar_pos, 
			bar_pic.local_pos()
			);
		
		bar_pic.draw(bar_plotter);

		if(draw_arrow_)
		{
			//left_arrow
			plotter.move_to(main_bar_pos.left, main_bar_pos.top);
			plotter.line_to(0.5, 0.0);
			plotter.line_to(main_bar_pos.right, main_bar_pos.top);
			plotter.close_path();
			plotter.set_color(colormap_.beyond_max());
			plotter.fill();
			//right_arrow
			plotter.move_to(main_bar_pos.left, main_bar_pos.bottom);
			plotter.line_to(main_bar_pos.right, main_bar_pos.bottom);
			plotter.line_to(0.5, 1.0);
			plotter.close_path();
			plotter.set_color(colormap_.beyond_min());
			plotter.fill();
		}
	
		Plotter axis_plotter = plotter.sub_plotter(
			Position(
				main_bar_pos.right, main_bar_pos.right,
				main_bar_pos.top, main_bar_pos.bottom
				),
			axis_.local_pos()
			);
		
		axis_.draw(axis_plotter);
		
		plotter.set_color(border_color_);
		plotter.set_line_width(border_width_);
		//Draw border
		plotter.move_to(main_bar_pos.left, main_bar_pos.bottom);
		plotter.line_to(main_bar_pos.left, main_bar_pos.top);
		if(draw_arrow_)
		{
			plotter.line_to(0.5, 0.0);
		}
		plotter.line_to(main_bar_pos.right, main_bar_pos.top);
		plotter.line_to(main_bar_pos.right, main_bar_pos.bottom);
		if(draw_arrow_)
		{
			plotter.line_to(0.5, 1.0);
		}
		plotter.close_path();
		plotter.stroke();

		//Draw ticks
		double tick_length = 1.0 * tick_length_ratio_ / 2;
		for(int i = 0; i < tick_pos.size(); ++i)
		{
			double tick_y_pos = main_bar_pos.bottom - (tick_pos[i] - tick_pos_min) / (tick_pos_max - tick_pos_min) * main_bar_pos.height() ;
			plotter.move_to(0.0, tick_y_pos);
			plotter.line_to(0.0 + tick_length, tick_y_pos);
			plotter.move_to(1.0, tick_y_pos);
			plotter.line_to(1.0 - tick_length, tick_y_pos);
		}
		plotter.stroke();
	}

	plotter.restore();
}


}
